//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Mon Feb 16 12:26:32 PST 2015 Adapted from binasc program.
// Last Modified: Sat Apr 21 10:52:19 PDT 2018 Removed using namespace std;
// Filename:      midifile/include/Binasc.h
// Website:       http://midifile.sapp.org
// Syntax:        C++11
// vim:           ts=3 noexpandtab
//
// description:   Interface to convert bytes between binary and ASCII forms.
//

#ifndef _BINASC_H_INCLUDED
#define _BINASC_H_INCLUDED

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <stdlib.h> /* needed for MinGW */

namespace smf {

    typedef unsigned char uchar;
    typedef unsigned short ushort;
    typedef unsigned long ulong;

    class Binasc {

    public:
        Binasc(void);

        ~Binasc();

        // functions for setting options:
        int setLineLength(int length);

        int getLineLength(void);

        int setLineBytes(int length);

        int getLineBytes(void);

        void setComments(int state);

        void setCommentsOn(void);

        void setCommentsOff(void);

        int getComments(void);

        void setBytes(int state);

        void setBytesOn(void);

        void setBytesOff(void);

        int getBytes(void);

        void setMidi(int state);

        void setMidiOn(void);

        void setMidiOff(void);

        int getMidi(void);

        // functions for converting into a binary file:
        int writeToBinary(const std::string &outfile,
                          const std::string &infile);

        int writeToBinary(const std::string &outfile,
                          std::istream &input);

        int writeToBinary(std::ostream &out,
                          const std::string &infile);

        int writeToBinary(std::ostream &out,
                          std::istream &input);

        // functions for converting into an ASCII file with hex bytes:
        int readFromBinary(const std::string &
        outfile,
                           const std::string &infile);

        int readFromBinary(const std::string &outfile,
                           std::istream &input);

        int readFromBinary(std::ostream &out,
                           const std::string &infile);

        int readFromBinary(std::ostream &out,
                           std::istream &input);

        // static functions for writing ordered bytes:
        static std::ostream &writeLittleEndianUShort(std::ostream &out,
                                                     ushort value);

        static std::ostream &writeBigEndianUShort(std::ostream &out,
                                                  ushort value);

        static std::ostream &writeLittleEndianShort(std::ostream &out,
                                                    short value);

        static std::ostream &writeBigEndianShort(std::ostream &out,
                                                 short value);

        static std::ostream &writeLittleEndianULong(std::ostream &out,
                                                    ulong value);

        static std::ostream &writeBigEndianULong(std::ostream &out,
                                                 ulong value);

        static std::ostream &writeLittleEndianLong(std::ostream &out,
                                                   long value);

        static std::ostream &writeBigEndianLong(std::ostream &out,
                                                long value);

        static std::ostream &writeLittleEndianFloat(std::ostream &out,
                                                    float value);

        static std::ostream &writeBigEndianFloat(std::ostream &out,
                                                 float value);

        static std::ostream &writeLittleEndianDouble(std::ostream &out,
                                                     double value);

        static std::ostream &writeBigEndianDouble(std::ostream &out,
                                                  double value);

        static std::string keyToPitchName(int key);

    protected:
        int m_bytesQ;       // option for printing hex bytes in ASCII output.
        int m_commentsQ;    // option for printing comments in ASCII output.
        int m_midiQ;        // output ASCII data as parsed MIDI file.
        int m_maxLineLength;// number of character in ASCII output on a line.
        int m_maxLineBytes; // number of hex bytes in ASCII output on a line.

    private:
        // helper functions for reading ASCII content to conver to binary:
        int processLine(std::ostream &out,
                        const std::string &input,
                        int lineNum);

        int processAsciiWord(std::ostream &out,
                             const std::string &input,
                             int lineNum);

        int processStringWord(std::ostream &out,
                              const std::string &input,
                              int lineNum);

        int processBinaryWord(std::ostream &out,
                              const std::string &input,
                              int lineNum);

        int processDecimalWord(std::ostream &out,
                               const std::string &input,
                               int lineNum);

        int processHexWord(std::ostream &out,
                           const std::string &input,
                           int lineNum);

        int processVlvWord(std::ostream &out,
                           const std::string &input,
                           int lineNum);

        int processMidiPitchBendWord(std::ostream &out,
                                     const std::string &input,
                                     int lineNum);

        int processMidiTempoWord(std::ostream &out,
                                 const std::string &input,
                                 int lineNum);

        // helper functions for reading binary content to convert to ASCII:
        int outputStyleAscii(std::ostream &out, std::istream &input);

        int outputStyleBinary(std::ostream &out, std::istream &input);

        int outputStyleBoth(std::ostream &out, std::istream &input);

        int outputStyleMidi(std::ostream &out, std::istream &input);

        // MIDI parsing helper functions:
        int readMidiEvent(std::ostream &out, std::istream &infile,
                          int &trackbytes, int &command);

        int getVLV(std::istream &infile, int &trackbytes);

        int getWord(std::string &word, const std::string &input,
                    const std::string &terminators, int index);

    };

} // end of namespace smf

#endif /* _BINASC_H_INCLUDED */



